# -*- coding: utf-8 -*-
import pygame, random, sys, time, pickle
import colorsnew as colorlib
from spitesutil2 import *

loop_return = True
theme = None
theme2 = None
theme3 = None
point = None
game_over = None
Highscore = []
DEBUG = False

myColorScheme = ColorScheme()

# the main game class. The stuff happens here!    
# actually, far to much stuff happens here.
# It should be splitted up into functions
# All window-relatet things should go to a Window class
class Game():
    """this is a docstring!"""
    
    # initializes everything
    # creates a (width x height) - window 
    # put's 50 blocks on the screen
    def __init__(self, width = WIDTH, height = HEIGHT):

        # just creates the window, doesn't draw it
        #self.screen = pygame.display.set_mode([width, height],pygame.FULLSCREEN) #Fullscreen
        self.screen = pygame.display.set_mode([width, height]) #windowed mode

        # hides the mouse pointer
        pygame.mouse.set_visible(False)

        # Blocks.
        # cretes a new list of sprites
        self.block_list = pygame.sprite.RenderPlain()

        # another list of sprites that will contain
        # all sprites, including player
        # Will be used later to draw it all
        self.all_sprites_list = pygame.sprite.RenderPlain()
        
        # the bad blocks
        self.bad_block_list = pygame.sprite.RenderPlain()
        
        # create 50 blocks, some of the bad
        for i in range(NUM_BLOCKS):
            #if random.randrange(100) < bad_blocks_prob:
            if len(self.bad_block_list) < NUM_BAD_BLOCKS:
                # the bad block is placed in the bad block list
                block = Block(colorlib.random_color('black'),20,15,True)
                self.bad_block_list.add(block)
                
            else:
                # a normal block
                block = Block(colorlib.random_color('light','red'), 20 + random.randrange(-8,9), 15 + random.randrange(-7,8))
                self.block_list.add(block)
            # random coordinates for the blocks, both bad and not
            block.rect.x = random.randrange(width)
            block.rect.y = random.randrange(height)
            
            # add the block to the list of blocks
            self.all_sprites_list.add(block)
        
        # player1 block
        # self.player1 is a block which is also a Sprite
        # red block!
        self.player1 = Block(myColorScheme.red, 25, 20)
        #self.player1 = Block(colorlib.random_color('red'),25,20)
        # middle of the screen
        self.player1.rect.x = (width//4)
        self.player1.rect.y = (height//2)
        # is in the list of all blocks
        self.all_sprites_list.add(self.player1)

        # player2 block
        # self.player2 is a block which is also a Sprite
        # yellow block!
        self.player2 = Block(myColorScheme.yellow, 25, 20)
        #self.player1 = Block(colorlib.random_color('red'),25,20)
        # middle of the screen
        self.player2.rect.x = (3*width//4)
        self.player2.rect.y = (height//2)
        # is in the list of all blocks
        self.all_sprites_list.add(self.player2)
        
        # movement
        self.player1_speed = [0, 0]
        self.player2_speed = [0, 0]
        
        # are we done yet?
        self.dead = [False,False]
        self.done = False
        
        # will be used later to set the update speed
        self.clock = pygame.time.Clock()
        
        # a list with the score of player [1,2]
        self.score = [0,0]
        
        # will be set to true
        # if you hold down some key
        self.down = [False,False]
        self.up = [False,False]
        self.left = [False,False]
        self.right = [False,False]
        self.brake = [False,False]
        self.pause = False
        # does extra stuff on the first game loop
        self.first_loop = True
        self.speed_mode = 2
        # creates two channels to play sounds on, bgm for music
        # and sxf for effects
        self.bgm = pygame.mixer.Channel(0)
        self.sxf = pygame.mixer.Channel(1)
        # starts the backgrund theme
        if self.bgm.get_sound() != theme3: self.bgm.play(theme3,-1)

    # spawns new random color blocks instead of the killed ones
    def spawn_new(self):
        # how many do we have?
        if NUM_BLOCKS > len(self.block_list):
            block = Block(colorlib.random_color('light','red'),block_dimensions[0],
                          block_dimensions[1])
            block.rect.x = random.randrange(WIDTH) # there is probably a screen.dimensions or smth
            block.rect.y = random.randrange(0, 20)
            self.block_list.add(block)
            self.all_sprites_list.add(block)
            if DEBUG:
                print ("Block spawned at ", block.rect.x, block.rect.y)
    
    def get_input(self):
        # takes input and updates the speed
        # of the player block
        # TODO white a seperate function to
        # set player speed
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            # keypress events
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    sys.exit()
                # Player 1
                if event.key == pygame.K_DOWN: self.down[0] = True 
                
                if event.key == pygame.K_UP: self.up[0] = True
                    
                if event.key == pygame.K_LEFT: self.left[0] = True

                if event.key == pygame.K_RIGHT: self.right[0] = True
                if self.dead[0]: 
                    self.down[0] = False
                    self.right[0] = False
                    self.up[0] = False
                    self.left[0] = False

                # Player 2
                if event.key == pygame.K_s: self.down[1] = True 
                
                if event.key == pygame.K_w: self.up[1] = True
                    
                if event.key == pygame.K_a: self.left[1] = True

                if event.key == pygame.K_d: self.right[1] = True

                if event.key == pygame.K_p: self.brake[0] = True

                if self.dead[1]: 
                    self.down[1] = False
                    self.right[1] = False
                    self.up[1] = False
                    self.left[1] = False            

                # and finally some fun dvorak stuff!
                if event.key == pygame.K_o:  self.speed_mode = 1
                if event.key == pygame.K_e:  self.speed_mode = 2
                if event.key == pygame.K_u:  self.speed_mode = 3

                if event.key == pygame.K_SPACE: self.pause = not self.pause
                
                    
            if event.type == pygame.KEYUP:
                # Player 1
                if event.key == pygame.K_DOWN: self.down[0] = False 
                
                if event.key == pygame.K_UP: self.up[0] = False
                    
                if event.key == pygame.K_LEFT: self.left[0] = False

                if event.key == pygame.K_RIGHT: self.right[0] = False
                # Player 2
                if event.key == pygame.K_s: self.down[1] = False
                
                if event.key == pygame.K_w: self.up[1] = False
                    
                if event.key == pygame.K_a: self.left[1] = False

                if event.key == pygame.K_d: self.right[1] = False

                if event.key == pygame.K_p: self.brake[0] = False
        
            
                    
        # set player speed
        # dec_func decelerates back to normal speed
        # acc_func accelerates in some direction
        if self.brake[0]:
            for i in range(5):
                self.player1_speed[0] += dec_func(self.player1_speed[0])
                self.player1_speed[1] += dec_func(self.player1_speed[1])
        # player 1        
        if self.up[0]:
            self.player1_speed[1] -= inc_func(self.speed_mode, self.player1_speed)
        else :
            self.player1_speed[1] += dec_func(self.player1_speed[1])
        
        if self.down[0]:
            self.player1_speed[1] += inc_func(self.speed_mode, self.player1_speed)
        else :
            self.player1_speed[1] += dec_func(self.player1_speed[1])
        
        if self.right[0]:
            self.player1_speed[0] += inc_func(self.speed_mode, self.player1_speed)
        else :
            self.player1_speed[0] += dec_func(self.player1_speed[0])

        if self.left[0]:
            self.player1_speed[0] -= inc_func(self.speed_mode, self.player1_speed)
        else :
            self.player1_speed[0] += dec_func(self.player1_speed[0])
        # player 2
        if self.up[1]:
            self.player2_speed[1] -= inc_func(self.speed_mode, self.player2_speed)
        else :
            self.player2_speed[1] += dec_func(self.player2_speed[1])
        
        if self.down[1]:
            self.player2_speed[1] += inc_func(self.speed_mode, self.player2_speed)
        else :
            self.player2_speed[1] += dec_func(self.player2_speed[1])
        
        if self.right[1]:
            self.player2_speed[0] += inc_func(self.speed_mode, self.player2_speed)
        else :
            self.player2_speed[0] += dec_func(self.player2_speed[0])

        if self.left[1]:
            self.player2_speed[0] -= inc_func(self.speed_mode, self.player2_speed)
        else :
            self.player2_speed[0] += dec_func(self.player2_speed[0])
        
                
                
                    
    def draw(self, max_x_pos = WIDTH, max_y_pos = HEIGHT):
        # fills the screen with color and 
        # updates block position
        # we should have a move(self)
        if DEBUG: print (self.player1.rect.x, self.player1.rect.y, self.player1_speed[0], self.player1_speed[1])
        # 
        self.screen.fill(myColorScheme.white)
        
        # player block comes back on the other side
        # if it moves outside of the screen
        if not self.dead[0]:
            if (self.player1.rect.x > max_x_pos):
                self.player1.rect.x = 0
            
            if (self.player1.rect.x < 0):
                self.player1.rect.x = max_x_pos
        
            if (self.player1.rect.y > max_y_pos):
                self.player1.rect.y = 0

            if (self.player1.rect.y < 0):
                self.player1.rect.y = max_y_pos

        if not self.dead[1]:
            if (self.player2.rect.x > max_x_pos):
                self.player2.rect.x = 0
            
            if (self.player2.rect.x < 0):
                self.player2.rect.x = max_x_pos
        
            if (self.player2.rect.y > max_y_pos):
                self.player2.rect.y = 0

            if (self.player2.rect.y < 0):
                self.player2.rect.y = max_y_pos
        
        self.player1.rect.x += self.player1_speed[0]
        self.player1.rect.y += self.player1_speed[1]
        self.player2.rect.x += self.player2_speed[0]
        self.player2.rect.y += self.player2_speed[1]
        #self.player_speed[0] = func2(self.player_speed[0])
        #self.player_speed[1] = func2(self.player_speed[1])

    def collide(self):
        blocks_hit_list1, blocks_hit_list2 = [],[]
        bad_blocks_hit_list1, bad_blocks_hit_list2 = [],[]
        if not self.dead[0]:
            blocks_hit_list1 = pygame.sprite.spritecollide(self.player1,
                                                           self.block_list,
                                                           True)
            bad_blocks_hit_list1 = pygame.sprite.spritecollide(self.player1, 
                                                               self.bad_block_list,
                                                               False)
        if not self.dead[1]:
            blocks_hit_list2 = pygame.sprite.spritecollide(self.player2,
                                                           self.block_list,
                                                           True)
            bad_blocks_hit_list2 = pygame.sprite.spritecollide(self.player2, 
                                                               self.bad_block_list,
                                                               False)

        player_hit = pygame.sprite.collide_rect(self.player1,self.player2)

        if len(bad_blocks_hit_list1) > 0:  #makes the block turn evil after it is killed!!!
            #self.all_sprites_list.remove(self.player1)
            self.player1.image.fill(myColorScheme.black)
            self.bad_block_list.add(self.player1)
            self.dead[0] = True 
            
        if len(bad_blocks_hit_list2) > 0:
            #self.all_sprites_list.remove(self.player2)
            self.player2.image.fill(myColorScheme.black)
            self.bad_block_list.add(self.player2)
            self.dead[1] = True

        if (self.dead[0] and self.dead[1]) or player_hit:
            global loop_return
            loop_return = False
            #sys.exit(0)
        
        return blocks_hit_list1, blocks_hit_list2
    
    
    def creep_around(self):
        for sprite in self.block_list:
            
            sprite.move(random.randrange(-2, 3), 
                        random.randrange(-2, 3), self.player1.rect.x, self.player1.rect.y,
                        self.player2.rect.x, self.player2.rect.y,self.dead)
            
        for sprite in self.bad_block_list:
            sprite.movebad(self.player1.rect.x, self.player1.rect.y,self.player2.rect.x,self.player2.rect.y,self.dead)

    def loop(self):
        global loop_return
        self.get_input()
        
        collide = self.collide()
        new_score = len(collide[0]),len(collide[1])
        
        if new_score[0] > 0:
            self.score[0] += new_score[0]
            self.sxf.play(point) 
        if new_score[1] > 0:
            self.score[1] += new_score[1]
            self.sxf.play(point)
            
        self.creep_around()
        self.spawn_new()
        if self.score[0] % max_score == max_score-1 and new_score[0] > 0:
            myColorScheme.new_Colors()
            
        
        

        self.draw()
        self.all_sprites_list.draw(self.screen)
        self.clock.tick(60)
        speed1 = (abs_speed(self.player1_speed))
        font = pygame.font.Font(None, 20 + int(speed1))
        if (speed1 > 30):
            text = font.render(str(speed1),
                               1,
                               (255, 0, 0))
        else :
            text = font.render(str(speed1),
                               1,
                               myColorScheme.black)

        speed2 = (abs_speed(self.player2_speed))
        font4 = pygame.font.Font(None, 20 + int(speed2))
        if (speed2 > 30):
            text4 = font4.render(str(speed2),
                               1,
                               (255, 0, 0))
        else :
            text4 = font4.render(str(speed2),
                               1,
                               myColorScheme.black)
        
        textpos = text.get_rect()
        textpos.top = HEIGHT - 200
        textpos4 = text4.get_rect()
        textpos4.top = HEIGHT - 200
        textpos4.right = WIDTH
        
        font2 = pygame.font.Font(None, 36)
        text2 = font2.render(str(self.score[0]), 1, myColorScheme.red)
        text3 = font2.render(str(self.score[1]), 1, myColorScheme.yellow)
        textpos2 = text.get_rect()
        textpos2.top = HEIGHT-30
        textpos3 = text3.get_rect()
        textpos3.top = HEIGHT-30
        textpos3.right = WIDTH
        
        self.screen.blit(text, textpos)
        self.screen.blit(text2, textpos2)
        self.screen.blit(text3, textpos3)
        self.screen.blit(text4, textpos4)
        #print(abs_speed(self.player_speed))
        pygame.display.flip()
        
        #font_str = pygame.font.get_default_font()
        

        
        if self.first_loop:
            time.sleep(1)
            self.first_loop = False
        if not(loop_return):
            if self.bgm.get_sound() != theme2: self.bgm.play(game_over)
            print ('Röd fick:', self.score[0], 'poäng!')
            print ('Gul fick:', self.score[1], 'poäng!')
            if self.score[0] > Highscore[0]:
                self.new_highscore()
            time.sleep(4)
            return False
        else : return True

    def new_highscore(self):
        font = pygame.font.Font(None,36)
        text = font.render('New Highscore!',1,myColorScheme.black)
        self.screen.blit(text,(0,HEIGHT-60))
        pygame.display.flip()
        Highscore[0] = self.score[0]
        Highscore.sort()
        f = open('highscore2.spites','wb')
        pickle.dump(Highscore,f)
        f.close()
        
  

def main():
    global theme,theme2,theme3,point,game_over,Highscore

    # loads the highscore from highscore2.spites
    try:
        f = open('highscore2.spites','rb')
        Highscore = pickle.load(f)
        f.close()
    except IOError:
        Highscore = [0,0,0,0,0]

    ljud = pygame.mixer.Sound
    pygame.font.init()
    pygame.mixer.init()
    theme = ljud('Theme.ogg')
    theme3 = ljud('Theme2.ogg')
    point = ljud('point.wav')
    game_over = ljud('game_over.ogg')
    c = 0
    while True:
        global loop_return
        loop_return = True
        newGame = Game()
        print('--- New Game ---')
        while newGame.loop():
            while newGame.pause:
                newGame.bgm.set_volume(0.5)
                newGame.get_input()
        newGame.bgm.set_volume(1.0)
main()
